package com.jichangxiu.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.jichangxiu.common.annotation.Dynamic;
import com.jichangxiu.common.annotation.Scope;
import com.jichangxiu.common.entity.bo.ValidateBos;
import com.jichangxiu.common.exception.ServiceException;
import com.jichangxiu.common.utils.ConvertUtils;
import com.jichangxiu.framework.service.impl.BaseServiceImpl;
import com.jichangxiu.framework.utils.NoUtils;
import com.jichangxiu.framework.utils.SecurityUtils;
import com.jichangxiu.framework.utils.ValidateUtils;
import com.jichangxiu.system.entity.bo.SysConfigBo;
import com.jichangxiu.system.entity.dto.add.AddSysConfig;
import com.jichangxiu.system.entity.dto.edit.EditSysConfig;
import com.jichangxiu.system.entity.dto.query.QuerySysConfig;
import com.jichangxiu.system.entity.po.SysConfig;
import com.jichangxiu.system.entity.vo.SysConfigVo;
import com.jichangxiu.system.enums.ConfigType;
import com.jichangxiu.system.mapper.SysConfigMapper;
import com.jichangxiu.system.service.SysConfigService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * SysConfigServiceImpl:
 *
 * @author JiChangXiu
 * @create 2024-06-28 13:44:09
 */
@Service
public class SysConfigServiceImpl extends BaseServiceImpl<SysConfigMapper, SysConfig, SysConfigVo> implements SysConfigService {

    /**
     * 新增系统配置
     *
     * @param addSysConfig 新增系统配置视图对象
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(AddSysConfig addSysConfig) {
        return getBaseMapper().insert(addAndEditValidBo(ConvertUtils.convert(addSysConfig, SysConfigBo.class))) > 0;
    }

    /**
     * 单（多）选删除系统配置
     *
     * @param idList 系统配置主键列表
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean del(List<String> idList) {
        return getBaseMapper().deleteBatchIds(delValid(idList)) > 0;
    }

    /**
     * 修改系统配置
     *
     * @param editSysConfig 修改系统配置视图对象
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(EditSysConfig editSysConfig) {
        return getBaseMapper().updateById(addAndEditValidBo(ConvertUtils.convert(editSysConfig, SysConfigBo.class))) > 0;
    }

    /**
     * 根据主键查询系统配置
     *
     * @param id       系统配置主键
     * @param isExtend 是否扩展
     * @return 系统配置详情
     */
    @Dynamic
    @Override
    public SysConfigVo info(@NotBlank(message = "主键不能为空") String id, Boolean isExtend) {
        SysConfigVo sysConfigVo = getBaseMapper().selectJoinOne(SysConfigVo.class, buildQueryWrapper(QuerySysConfig.builder().id(id).build()));
        if (Boolean.TRUE.equals(isExtend) && ObjectUtil.isNotEmpty(sysConfigVo))
            sysConfigVo = renderSysConfigVoList(ListUtil.toList(sysConfigVo)).get(0);
        return sysConfigVo;
    }

    /**
     * （可分页）查询系统配置列表
     *
     * @param querySysConfig 查询视图对象
     * @return （分页）系统配置列表
     */
    @Dynamic
    @Override
    public Page<SysConfigVo> lists(QuerySysConfig querySysConfig) {
        Page<SysConfigVo> sysConfigVoPage = getBaseMapper().selectJoinPage(startPage(), SysConfigVo.class, buildQueryWrapper(querySysConfig));
        if (Boolean.TRUE.equals(querySysConfig.getIsExtend()))
            sysConfigVoPage.setRecords(renderSysConfigVoList(sysConfigVoPage.getRecords()));
        return sysConfigVoPage;
    }

    /**
     * 新增 / 修改 前校验
     *
     * @param sysConfigBo 校验用业务对象
     * @return 数据库操作对象
     */
    private SysConfig addAndEditValidBo(SysConfigBo sysConfigBo) {
        SysConfig sysConfig = ConvertUtils.convert(sysConfigBo, SysConfig.class);
        if (ObjectUtil.isNull(sysConfig))
            throw new ServiceException("待校验对象为空");
        List<ValidateBos> validateBosList = Stream.of(
                ValidateUtils.createNeValidateBos(ValidateUtils.createValidateBo(SysConfig::getId, sysConfig.getId(), "主键")),
                ValidateUtils.createOrEqValidateBos(
                        ValidateUtils.createValidateBo(SysConfig::getNo, sysConfig.getNo(), "编码"),
                        ValidateUtils.createValidateBo(SysConfig::getCode, sysConfig.getCode(), "标识"),
                        ValidateUtils.createValidateBo(SysConfig::getName, sysConfig.getName(), "名称"),
                        ValidateUtils.createValidateBo(SysConfig::getKey, sysConfig.getKey(), "键名"),
                        ValidateUtils.createValidateBo(SysConfig::getValue, sysConfig.getValue(), "键值"),
                        ValidateUtils.createValidateBo(SysConfig::getRemark, sysConfig.getRemark(), "备注"))
        ).collect(Collectors.toList());
        // 唯一校验
        ValidateUtils.uniqueValidate(this::countWrapper, validateBosList);
        if (ConfigType.SYSTEM_CONFIG.name().equals(sysConfig.getType()))
            sysConfig.setUserId(null);
        else if (ConfigType.USER_CONFIG.name().equals(sysConfig.getType()))
            sysConfig.setUserId(SecurityUtils.getUserId());
        if (StrUtil.isEmpty(sysConfig.getId())) {
            // 新增
            sysConfig.setNo(NoUtils.createNo(SecurityUtils.getTenantId(), "config"));
            sysConfig.setTenantId(SecurityUtils.getTenantId());
            return sysConfig;
        } else {
            // 修改
            SysConfig dbSysConfig = getById(sysConfig.getId());
            BeanUtil.copyProperties(sysConfig, dbSysConfig, true);
            return dbSysConfig;
        }
    }

    /**
     * 删除前校验
     *
     * @param idList 主键列表
     * @return 主键列表
     */
    private List<String> delValid(List<String> idList) {
        if (ObjectUtil.isEmpty(idList))
            throw new ServiceException("待校验主键列表为空");
        return idList;
    }

    /**
     * 渲染视图
     *
     * @param sysConfigVoList 视图列表
     * @return 渲染后的视图列表
     */
    private List<SysConfigVo> renderSysConfigVoList(List<SysConfigVo> sysConfigVoList) {
        if (ObjectUtil.isNotEmpty(sysConfigVoList)) {
            // todo 扩展信息填入
        }
        return sysConfigVoList;
    }

    /**
     * 构建查询条件
     *
     * @param querySysConfig 查询用业务对象
     * @return 查询条件
     */
    private MPJLambdaWrapper<SysConfig> buildQueryWrapper(QuerySysConfig querySysConfig) {
        MPJLambdaWrapper<SysConfig> lambdaQueryWrapper = new MPJLambdaWrapper<SysConfig>().selectAll(SysConfig.class);
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysConfig.getId()), SysConfig::getId, querySysConfig.getId());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysConfig.getNo()), SysConfig::getNo, querySysConfig.getNo());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(querySysConfig.getCode()), SysConfig::getCode, querySysConfig.getCode());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(querySysConfig.getName()), SysConfig::getName, querySysConfig.getName());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysConfig.getType()), SysConfig::getType, querySysConfig.getType());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysConfig.getKey()), SysConfig::getKey, querySysConfig.getKey());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysConfig.getValue()), SysConfig::getValue, querySysConfig.getValue());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysConfig.getUserId()), SysConfig::getUserId, querySysConfig.getUserId());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(querySysConfig.getSort()), SysConfig::getSort, querySysConfig.getSort());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(querySysConfig.getRemark()), SysConfig::getRemark, querySysConfig.getRemark());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(querySysConfig.getEnabled()), SysConfig::getEnabled, querySysConfig.getEnabled());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(querySysConfig.getEnabledBy()), SysConfig::getEnabledBy, querySysConfig.getEnabledBy());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(querySysConfig.getEnabledTime()), SysConfig::getEnabledTime, querySysConfig.getEnabledTime());
        lambdaQueryWrapper.apply(StrUtil.isNotEmpty(querySysConfig.getScope()), querySysConfig.getScope());
        lambdaQueryWrapper.orderByAsc(SysConfig::getSort);
        return lambdaQueryWrapper;
    }

}